package math;

import java.math.BigInteger;

public class IntegerConstant implements NumericConstant {

  public static final IntegerConstant MINUS_ONE = new IntegerConstant(
      BigInteger.valueOf(-1));

  public static final IntegerConstant ZERO = new IntegerConstant(
      BigInteger.ZERO);

  public static final IntegerConstant ONE = new IntegerConstant(BigInteger.ONE);

  public static final IntegerConstant TWO = new IntegerConstant(2);
  
  public static final IntegerConstant THREE = new IntegerConstant(3);
  
  public static final IntegerConstant FOUR = new IntegerConstant(4);
  
  public static final IntegerConstant FIVE = new IntegerConstant(5);
  
  public static final IntegerConstant SIX = new IntegerConstant(6);
  
  public static final IntegerConstant SEVEN = new IntegerConstant(7);

  public static final IntegerConstant EIGHT = new IntegerConstant(8);

  public static final IntegerConstant NINE = new IntegerConstant(9);

  public static final IntegerConstant TEN = new IntegerConstant(10);
private BigInteger value;

  public IntegerConstant(BigInteger value) {
    this.value = value;
  }

  public IntegerConstant(long value) {
    this.value = BigInteger.valueOf(value);
  }

  @Override
  public ArithmeticExpression derivate(Variable var) {
    return IntegerConstant.ZERO;
  }

  @Override
  public int countMembers() {
    return 1;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof IntegerConstant) {
      IntegerConstant ic2 = (IntegerConstant) obj;
      return ic2.value.compareTo(value) == 0;
    } else
      return false;
  }

  @Override
  public int getPriority() {
    return 1;
  }
  
  @Override
  public int hashCode() {
    return value.hashCode();
  }

  public BigInteger getValue() {
    return value;
  }

  @Override
  public boolean isOne() {
    return value.compareTo(BigInteger.ONE) == 0;
  }

  @Override
  public boolean isZero() {
    return value.compareTo(BigInteger.ZERO) == 0;
  }

  @Override
  public boolean matches(Expression expr) {
    if (expr instanceof IntegerConstant) {
      IntegerConstant eIntConst = (IntegerConstant) expr;
      return value.equals(eIntConst.getValue());
    } else
      return false;
  }

  @Override
  public IntegerConstant negate() {
    return new IntegerConstant(value.negate());
  }

  @Override
  public ArithmeticExpression simplify() {
    return this;
  }

  @Override
  public String toString() {
    return value.toString();
  }

  @Override
  public ArithmeticExpression add(NumericConstant value) {
    if (value instanceof IntegerConstant){
      IntegerConstant i2 = (IntegerConstant) value;
      return new IntegerConstant(this.value.add(i2.getValue()));
    }
    return Add.createAdd(this, value);
  }

  @Override
  public ArithmeticExpression sub(NumericConstant value) {
    if (value instanceof IntegerConstant){
      IntegerConstant i2 = (IntegerConstant) value;
      return new IntegerConstant(this.value.subtract(i2.getValue()));
    }
    return Add.createAdd(this, Negation.createNegation(value));
  }

  @Override
  public ArithmeticExpression mult(NumericConstant value) {
    if (value instanceof IntegerConstant){
      IntegerConstant i2 = (IntegerConstant) value;
      return new IntegerConstant(this.value.multiply(i2.getValue()));
    }
    return Mult.createMult(this, value);
  }

  @Override
  public <R> R accept(ExpressionVisitor<R> visitor) {
    return visitor.visitIntegerConstant(this);
  }
}